package jp.androidgroup.chiba.androidresearch.ui;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import jp.androidgroup.chiba.androidresearch.Common;
import jp.androidgroup.chiba.androidresearch.R;
import jp.androidgroup.chiba.androidresearch.SdbUpdateService;
import jp.androidgroup.chiba.androidresearch.data.Base;
import jp.androidgroup.chiba.androidresearch.data.Counter;
import jp.androidgroup.chiba.androidresearch.db.DatabaseHelper;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 投稿エントリーの追加を行うクラス<br />
 * 集計画面は管理が楽なのでダイアログから通常の画面へ変更<br />
 * <br />
 * 集計に利用するボタンは通常のButtonを利用しているが、ImageButtonに切り替える可能性大<br />
 * （文字で内容を表示しきれない、イメージの方が直感的に理解できる、的な。最悪、クリック時にトーストで中身を表示もありかもしれない）
 *
 * @author noxi
 *
 */
public final class CounterAddActivity extends Activity {

	/**
	 * DB INSERT用ContentValues作成
	 *
	 * @param counter
	 * @return
	 */
	static ContentValues createContentValues(Counter counter) {

		ContentValues values = new ContentValues();
		values.put("Id", counter.getId());
		values.put("Email", Common.getUserInfo().getEmail());
		values.put("UserName", Common.getUserInfo().getName());
		values.put("ContributeDate", counter.getContributeDate());
		values.put("PlaceId", counter.getPlaceId());
		values.put("TimeId", counter.getTimeId());
		values.put("OccupationId", counter.getOccupationId());
		values.put("Sex", counter.getSex());
		values.put("Memo", counter.getMemo());
		values.put("DetailMemo", counter.getDetailMemo());
		values.put("Num", counter.getNum());
		values.put("UseId", counter.getUseId());
		values.put("DetailNum", counter.getDetailNum());
		values.put("DetailNo", counter.getDetailNo());
		values.put("Key", counter.getKey());
		values.put("CreateDate", counter.getCreateDate());

		return values;
	}



	/**
	 * CounterEditActivityからCounterAddActivityへのパラメーター
	 */
	public static final String EXTRA_COUNTER = "AndroidResearch.CounterAddActivity.Counter";


	private LayoutInflater mInflater;

	/**
	 * 日付
	 */
	private String mDate;
	/**
	 * 時間
	 */
	private String mTime;
	/**
	 * 場所
	 */
	private String mPlace;
	/**
	 * メモ
	 */
	private String mMemo;

	/**
	 * 現在の入力内容
	 */
	private Counter mCounter;
	/**
	 * 入力内容
	 */
	private List<Counter> mData;
	/**
	 * 人数
	 */
	private int mCount;

	/**
	 * 人数カウントEditTextの表示テキスト
	 */
	private Editable mEditableCount;
	private Editable mEditableMemo;

	private Button btnEntry;
	private Button btnNext;
	private Button btnCancel;

	private Button[] btnUse;
	private Button[] btnSex;
	private Button[] btnOccupation;

	private Button btnCountMinus;
	private Button btnCountPlus;
	private EditText textCount;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
		setContentView(R.layout.activity_counter_add);

		mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		// Widget初期化
		btnEntry = (Button) findViewById(R.id.btn_entry);
		btnEntry.setOnClickListener(clickListenerEntry);

		btnNext = (Button) findViewById(R.id.btn_next);
		btnNext.setOnClickListener(clickListenerNext);

		btnCancel = (Button) findViewById(R.id.btn_cancel);
		btnCancel.setOnClickListener(clickListenerCancel);


		// OS区分
		btnUse = new Button[Common.getUseList().size()];
		setButton(btnUse, clickListenerUse, Common.getUseList(), R.id.layout_use);

		// 性別
		btnSex = new Button[2];

		View view = findViewById(R.id.layout_sex_male);
		btnSex[0] = (Button) view.findViewById(R.id.button);
		btnSex[0].setOnClickListener(clickListenerSex);
		btnSex[0].setTag(getString(R.string.v_man));
		TextView text = (TextView) view.findViewById(R.id.text);
		text.setText(R.string.l_man);

		view = findViewById(R.id.layout_sex_female);
		btnSex[1] = (Button) view.findViewById(R.id.button);
		btnSex[1].setOnClickListener(clickListenerSex);
		btnSex[1].setTag(getString(R.string.v_woman));
		text = (TextView) view.findViewById(R.id.text);
		text.setText(R.string.l_woman);

		// 職業
		btnOccupation = new Button[Common.getOccList().size()];
		setButton(btnOccupation, clickListenerOcc, Common.getOccList(), R.id.layout_occupation);

		// カウント
		btnCountMinus = (Button) findViewById(R.id.btn_count_minus);
		btnCountMinus.setOnClickListener(clickListenerCount);

		btnCountPlus = (Button) findViewById(R.id.btn_count_plus);
		btnCountPlus.setOnClickListener(clickListenerCount);

		textCount = (EditText) findViewById(R.id.edittext_count);
		mEditableCount = textCount.getEditableText();

		EditText textMemo = (EditText) findViewById(R.id.edittext_detailmemo);
		mEditableMemo = textMemo.getEditableText();


		// 集計情報の取得
		Counter data = getIntent().getParcelableExtra(EXTRA_COUNTER);
		// 集計情報がnull ＝ 新規登録
		if (data == null) {
			// 一時記録リストの初期化
			mData = new ArrayList<Counter>();

			// 日時・場所選択ダイアログの表示
			new CounterInfoDialog(this, new CounterInfoDialog.OnClickListener() {

				@Override
				public void onPositiveClick(String date, String time, String place, String memo) {
					mDate = date;
					mTime = time;
					mPlace = place;
					mMemo = memo;

					CounterAddActivity.this.resetView();
				}

				@Override
				public void onNegativeClick() {
					CounterAddActivity.this.finish();
				}
			})
			.show();
		}
		// 集計情報がnullじゃない場合 ＝ 過去の集計情報を変更する場合
		else {
			mDate = data.getContributeDate();
			mTime = data.getTimeId();
			mPlace = data.getPlaceId();
			mMemo = data.getMemo();
			mData = data.getDetails();

			if (data.getId() == null) {
				resetView();
			} else {
				resetView(data);
			}
		}
	}

	/*
	 * 戻るボタンでActivityを終了させない（登録されてませんダイアログの表示）
	 *
	 * (non-Javadoc)
	 * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			showDialogCancel();
			return true;
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}

	/**
	 * ボタンの作成
	 *
	 * @param buttons ボタン群
	 * @param listener ボタンのリスナー
	 * @param map ボタン作成元のマップ情報
	 * @param layoutId ボタンを入れる親のレイアウトID
	 */
	private void setButton(Button[] buttons, View.OnClickListener listener,
			LinkedHashMap<String, ? extends Base> map, int layoutId) {
		// 親ビューの取得
		LinearLayout root = (LinearLayout) findViewById(layoutId);

		// 一段目
		LinearLayout layout0 = new LinearLayout(this);
		layout0.setLayoutParams(new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
		layout0.setOrientation(LinearLayout.HORIZONTAL);

		final int size = map.size();
		String[] keys = map.keySet().toArray(new String[map.size()]);

		for (int i = 0 ; i < (size < 4 ? size : 4) ; i++) {
			View part = mInflater.inflate(R.layout.counter_add_part_button, layout0, false);
			Base data = map.get(keys[i]);

			// ボタンの取得
			buttons[i] = (Button) part.findViewById(R.id.button);
			buttons[i].setOnClickListener(listener);
			// ボタンに職業情報をタグ付けしておく
			buttons[i].setTag(data);

			// テキスト表示
			TextView text = (TextView) part.findViewById(R.id.text);
			text.setText(addBreak(data.getName()));

			layout0.addView(part);
		}
		root.addView(layout0);


		// 2段目以降
		if (size > 4) {
			// dip -> px
			final float scale = getResources().getDisplayMetrics().density;
			// レイアウト同士の高さマージンは6dip
			final int marginTop = (int) (6 * scale);

			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
			params.setMargins(0, marginTop, 0, 0);

			final int stageCount = (size - 1) / 4;
			for (int i = 0 ; i < stageCount ; i++) {
				LinearLayout parent = new LinearLayout(this);
				parent.setLayoutParams(params);
				parent.setOrientation(LinearLayout.HORIZONTAL);

				for (int j = (i * 4 + 4) ; j < (size < (i * 4 + 8) ? size : (i * 4 + 8)) ; j++) {
					View part = mInflater.inflate(R.layout.counter_add_part_button, parent, false);
					Base data = map.get(keys[j]);

					// ボタンの取得
					buttons[j] = (Button) part.findViewById(R.id.button);
					buttons[j].setOnClickListener(listener);
					// ボタンに職業情報をタグ付けしておく
					buttons[j].setTag(data);

					// テキスト表示
					TextView text = (TextView) part.findViewById(R.id.text);
					text.setText(addBreak(data.getName()));

					parent.addView(part);
				}

				root.addView(parent);
			}
		}
	}

	/**
	 * ボタンのラベルに改行を追加する
	 *
	 * @param ori ボタンのラベル
	 * @return 改行済みのラベル
	 */
	private String addBreak(String ori) {
		if (ori.indexOf("利用者") > 0) {
			return ori.replace("利用者", "\n利用者");
		} else if (ori.indexOf("(") > 0) {
			return ori.replace("(", "\n(");
		} else {
			return ori;
		}
	}

	/**
	 * ボタンを有効にする
	 *
	 * @param buttons
	 */
	private void setBtnEnabled(Button[] buttons) {
		for (Button btn : buttons) {
			btn.setEnabled(true);
		}
	}

	/**
	 * 全Widget値を初期化
	 */
	private void resetView() {
		setBtnEnabled(btnUse);
		setBtnEnabled(btnSex);
		setBtnEnabled(btnOccupation);

		btnCountMinus.setEnabled(false);
		btnCountPlus.setEnabled(true);
		mEditableMemo.clear();

		// カウンターの初期化
		mCounter = new Counter();
		mCounter.setContributeDate(mDate);
		mCounter.setTimeId(mTime);
		mCounter.setPlaceId(mPlace);
		mCounter.setMemo(mMemo);

		mCount = 1;
		changeCount();

		try {
			InputMethodManager inputMethodManager =
					(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
		} catch (Exception e) {}
	}

	/**
	 * 既存の情報に合わせてボタンの有効・非有効化
	 *
	 * @param counter
	 */
	private void resetView(Counter counter) {
		mCounter = counter;
		mData = counter.getDetails();

		// OS区分
		for (Button btn : btnUse) {
			Base base = (Base) btn.getTag();
			if (base.getId().equals(counter.getUseId())) {
				btn.setEnabled(false);
			} else {
				btn.setEnabled(true);
			}
		}
		// 性別
		for (Button btn : btnSex) {
			String sex = (String) btn.getTag();
			if (sex.equals(counter.getSex())) {
				btn.setEnabled(false);
			} else {
				btn.setEnabled(true);
			}
		}
		// 職業
		for (Button btn : btnOccupation) {
			Base base = (Base) btn.getTag();
			if (base.getId().equals(counter.getOccupationId())) {
				btn.setEnabled(false);
			} else {
				btn.setEnabled(true);
			}
		}
		// カウント
		mCount = Integer.parseInt(counter.getNum());
		btnCountMinus.setEnabled(mCount > 1 ? true : false);
		btnCountPlus.setEnabled(true);
		changeCount();

		// メモ
		mEditableMemo.clear();
		mEditableMemo.append(counter.getDetailMemo());


		try {
			InputMethodManager inputMethodManager =
					(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
		} catch (Exception e) {}
	}

	/**
	 * 集計画面でキャンセルを押したときの確認ダイアログ
	 */
	private void showDialogCancel() {
		new AlertDialog.Builder(this)
		.setMessage(R.string.m_entry_cancel)
		// キャンセルを実行
		// Activityを終了する
		.setPositiveButton(R.string.l_cancel_ok, new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				CounterAddActivity.this.finish();
			}
		})
		// キャンセルのキャンセル
		// 特に何もしない
		.setNegativeButton(R.string.l_cancel_no, (DialogInterface.OnClickListener) null)
		.create().show();
	}

	/**
	 * ボタンが全て押されているかチェックする（Counterの中身をチェックする）
	 *
	 * @param counter
	 * @return
	 */
	public static boolean checkNull(Counter counter) {
		if (counter.getUseId() == null) {
			return false;
		} else if (counter.getSex() == null) {
			return false;
		} else if (counter.getOccupationId() == null) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 登録ボタンのクリックリスナー<br />
	 * エントリーを確定し、Activityを終了する
	 */
	private View.OnClickListener clickListenerEntry = new View.OnClickListener() {

		public void onClick(View v) {
			// 入力内容のチェック
			// 不十分だった場合でも、一つ以上保存されたものがあれば確定する
			if (checkNull(mCounter) == false && mData.size() == 0) {
				Toast.makeText(CounterAddActivity.this,
						R.string.m_entry_not_enough, Toast.LENGTH_SHORT).show();
				return;
			} else if (checkNull(mCounter) == true) {
				// エントリーの確定
				/*if (mCounter.getId() == null) {
					try {
						mCounter.setId(Counter.getUniqKey(CounterAddActivity.this,
								new SimpleDateFormat("MM月dd日").format(
										new SimpleDateFormat("yyyy-MM-dd").parse(mDate))));
					} catch (ParseException e) {
						e.printStackTrace();
						Toast.makeText(CounterAddActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
					}
				}*/
				mCounter.setNum(String.valueOf(mCount));
				mCounter.setDetailMemo(mEditableMemo.toString().trim());
				mData.add(mCounter);
			}

			// 集計を内部DBに保存
			try {
				insertData();
				// Sdb update service 起動
				Intent intent = new Intent(CounterAddActivity.this, SdbUpdateService.class);
				startService(intent);
			} catch (SQLiteException e) {
				e.printStackTrace();
				Toast.makeText(CounterAddActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
			}


			// 返り値の設定
			CounterAddActivity.this.setResult(Activity.RESULT_OK);
			CounterAddActivity.this.finish();

		}
	};

	private void insertData() throws SQLiteException {

		DatabaseHelper helper = new DatabaseHelper(this);
		SQLiteDatabase db = helper.getWritableDatabase();

		int detailno;
		String key;
		final String whereClause = "Id=?";
		db.beginTransaction();
		try {
			key = null;
			detailno = 1;
			for (Counter counter : mData) {
				// グループキーを取得
				if(key == null){
					key = Counter.getUniqKey(CounterAddActivity.this, counter.getContributeDate());
				}
				// IDを設定
				if(counter.getId() == null){
					counter.setId(key + "_" + String.format("%1$03d", detailno));
				}
				counter.setDetailNo(String.valueOf(detailno));
				counter.setDetailNum(String.valueOf(mData.size()));
				counter.setCreateDate(Common.getNowDate());
				counter.setKey(key);
				final String[] whereArgs = {counter.getId()};
				ContentValues values = createContentValues(counter);
				int rows = db.update("Counter", values, whereClause, whereArgs);
				if (rows == 0) {
					db.insert("Counter", null, values);
				}
				detailno++;
			}
			db.setTransactionSuccessful();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} finally {
			db.endTransaction();
		}
	}

	/**
	 * 次へボタンのクリックリスナー<br />
	 * エントリーを記録してViewの状態をリセットする
	 */
	private View.OnClickListener clickListenerNext = new View.OnClickListener() {

		public void onClick(View v) {
			// 入力内容のチェック
			if (checkNull(mCounter) == false) {
				Toast.makeText(CounterAddActivity.this,
						R.string.m_entry_not_enough, Toast.LENGTH_SHORT).show();
			} else {
				// エントリーの確定
				/*if (mCounter.getId() == null) {
					try {
						mCounter.setId(Counter.getUniqKey(CounterAddActivity.this,
								new SimpleDateFormat("MM月dd日").format(
										new SimpleDateFormat("yyyy-MM-dd").parse(mDate))));
					} catch (ParseException e) {
						e.printStackTrace();
						Toast.makeText(CounterAddActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
					}
				}
				*/
				mCounter.setNum(String.valueOf(mCount));
				mCounter.setDetailMemo(mEditableMemo.toString().trim());
				mData.add(mCounter);

				CounterAddActivity.this.resetView();
			}
		}
	};

	/**
	 * キャンセルボタンのクリックリスナー<br />
	 * 確認ダイアログを表示の上、Activityを終了する
	 */
	private View.OnClickListener clickListenerCancel = new View.OnClickListener() {

		public void onClick(View v) {
			CounterAddActivity.this.showDialogCancel();
		}
	};

	/**
	 * OS区分ボタンのクリックリスナー<br />
	 * クリックされたボタンをFALSE、他をTRUEに
	 */
	private View.OnClickListener clickListenerUse = new View.OnClickListener() {

		public void onClick(View view) {
			Base base = (Base) view.getTag();

			for (Button button : btnUse) {
				Base b = (Base) button.getTag();
				if (base.getId().equals(b.getId())) {
					button.setEnabled(false);
				} else {
					button.setEnabled(true);
				}
			}

			mCounter.setUseId(base.getId());
		}
	};

	/**
	 * 性別ボタンのクリックリスナー
	 */
	private View.OnClickListener clickListenerSex = new View.OnClickListener() {

		public void onClick(View view) {
			String sex = (String) view.getTag();

			for (Button button : btnSex) {
				String s = (String) button.getTag();
				if (sex.equals(s)) {
					button.setEnabled(false);
				} else {
					button.setEnabled(true);
				}
			}

			mCounter.setSex(sex);
		}
	};

	/**
	 * 職業ボタンのクリックリスナー
	 */
	private View.OnClickListener clickListenerOcc = new View.OnClickListener() {

		public void onClick(View view) {
			Base base = (Base) view.getTag();

			for (Button button : btnOccupation) {
				Base data = (Base) button.getTag();

				if (base.getId().equals(data.getId())) {
					button.setEnabled(false);
				} else {
					button.setEnabled(true);
				}
			}

			mCounter.setOccupationId(base.getId());
		}
	};

	/**
	 * カウントボタンのリスナー
	 */
	private View.OnClickListener clickListenerCount = new View.OnClickListener() {

		public void onClick(View view) {
			final int id = view.getId();

			if (id == R.id.btn_count_plus) {
				mCount++;
			} else {
				mCount--;
			}
			changeCount();

			// マイナスボタンの無効化
			btnCountMinus.setEnabled(mCount == 1 ? false : true);
		}
	};

	/**
	 * カウントを更新する
	 */
	private void changeCount() {
		mEditableCount.clear();
		mEditableCount.append(String.valueOf(mCount));
	}

}
